﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Practices.Unity;

using FluentValidation;

using CloudSoft.Extensions;

using ERPStore.Extensions;

namespace ERPStore.Services
{
	public class FluentValidatorService : ERPStore.Services.IValidatorService
	{
		public FluentValidatorService()
		{
			Container = GlobalConfiguration.Configuration.DependencyResolver.GetContainer();
		}

		protected Microsoft.Practices.Unity.IUnityContainer Container { get; set; }

		#region IValidatorService Members

		public virtual void Configure()
		{
			RegisterValidator<Models.ContactInfo, ModelValidators.ContactInfoValidator>("ContactInfo");
			RegisterValidator<Models.Address, ModelValidators.AddressValidator>("Address");
			// RegisterValidator<Models.OrderCart, ModelValidators.OrderCartValidator>("OrderCart");
			RegisterValidator<Models.Corporate, ModelValidators.CorporateValidator>("Corporate");
			RegisterValidator<Models.RegistrationUser, ModelValidators.RegistrationUserValidator>("RegistrationUser");
		}

		public virtual void RegisterValidator<Model, ModelValidator>(string validatorName)
		{
			var fromType = typeof(global::FluentValidation.IValidator<Model>);
			var toType = typeof(ModelValidator);
			Container.RegisterType(fromType, toType, validatorName, new ContainerControlledLifetimeManager());
		}

		public virtual List<Models.BrokenRule> Validate(object model)
		{
			// J'ai pas trouvé mieux pour le moment
			var validatorName = "Validator:" + model.GetType().FullName;
			var validators =  from type in Container.Registrations.Where(i => !i.Name.IsNullOrTrimmedEmpty() && i.Name.Equals(validatorName, StringComparison.InvariantCultureIgnoreCase)).Select(i => i.RegisteredType)
							  select Container.Resolve(type, validatorName);


			var validator = validators.FirstOrDefault();
			return ValidateWith(model, validator);
		}

		public virtual List<Models.BrokenRule> ValidateWith(object model, object vldr)
		{
			var validator = vldr as global::FluentValidation.IValidator;
			if (validator == null)
			{
				return new List<Models.BrokenRule>();
			}
			var validationResult = validator.Validate(model);
			if (validationResult == null
				|| validationResult.IsValid)
			{
				return new List<Models.BrokenRule>();
			}
			var result = new List<global::ERPStore.Models.BrokenRule>();
			foreach (var item in validationResult.Errors)
			{
				var brokenRule = result.SingleOrDefault(i => i.PropertyName == item.PropertyName);
				if (brokenRule == null)
				{
					brokenRule = new global::ERPStore.Models.BrokenRule();
					brokenRule.PropertyName = item.PropertyName;
				}
				brokenRule.ErrorList.Add(item.ErrorMessage);
				result.Add(brokenRule);
			}
			return result;

		}

		#endregion
	}
}
